/******************************************************************************
 * @file     stack_overrun_ptrn.c
 * @version  V0.10
 * $Revision: 3 $
 * $Date: 21/03/10 2:50p $
 * @brief    IEC60730 Program Counter Test
 * @note
 * SPDX-License-Identifier: Apache-2.0
 * Copyright (C) 2016-2020 Nuvoton Technology Corp. All rights reserved.
 ******************************************************************************/

#include <stdio.h>
#include "nuc980.h"
#include "IEC60730_CONTROL_PARAM.h"
#include "IEC60730_SAFETY_TEST_LIB.h"

extern uint32_t volatile g_u32RunTimeInit;
volatile uint32_t u32StackPtrn[4];
extern uint32_t const STACK_TEST_PTRN[];
volatile uint32_t* g_pu32StackPtrn;

/* please don't change "g_pu32StackPtrn" in other functions */
static void GetStackPtrnPtr(void)
{
    asm volatile
    (
        "push    {r0-r7}  \n"
        "ldr     r1, [%0] \n"
        "mov     r0, sp \n"
        "ldr     r2, =0x4000 \n"        /* 0x20: r0-r7 */
        "sub     r0, r0, r2 \n"             /* 0x18: SP-0x18 when enters this function*/
        "ldr     r2, =(0x20+0x18-0x10)  \n" /* 0x10: stack pattern area size*/
        "add     r0, r0, r2 \n"
        "str     r0, [r1] \n"
        "pop     {r0-r7} \n"
        "bx      lr  \n"
        :"=r"(g_pu32StackPtrn)
        :
        :
    );
}

static void CopyStackPtrn(void)
{
	uint32_t *pu32PtrnSrc, *pu32PtrnDest;

	/* get stored stack pattern pointer
		and saved in "g_pu32StackPtrn" */
	GetStackPtrnPtr();

	pu32PtrnSrc = (uint32_t*) STACK_TEST_PTRN;
	pu32PtrnDest = (uint32_t *)g_pu32StackPtrn;
	*pu32PtrnDest++ = *pu32PtrnSrc++;
	*pu32PtrnDest++ = *pu32PtrnSrc++;
	*pu32PtrnDest++ = *pu32PtrnSrc++;
	*pu32PtrnDest++ = *pu32PtrnSrc++;
}

void IEC60730_Stack_Test_RunTime_Init(void)
{
	CopyStackPtrn();
}

/**
 * 检测栈底的模型数据是否被篡改
 */
uint8_t IEC60730_Stack_Test_RunTime()
{
    uint32_t *pu32stackptrn;

    pu32stackptrn = (uint32_t *)g_pu32StackPtrn;

    if ((*pu32stackptrn++ == STACK_OVERRUN_PTRN0) &&
        (*pu32stackptrn++ == STACK_OVERRUN_PTRN1) &&
        (*pu32stackptrn++ == STACK_OVERRUN_PTRN2) &&
        (*pu32stackptrn   == STACK_OVERRUN_PTRN3) )

        return TEST_PASS;
    else
        return TEST_FAIL;
}


/*** (C) COPYRIGHT 2013 Nuvoton Technology Corp. ***/
